package com.leilei.config;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;

/**
 * @author lei
 * @create 2022-04-27 11:25
 * @desc 压缩配置，以解决设置了最小数据大小压缩无效的问题 min-response-size
 *
 * 默认情况下 返回的是json对象，即Content-Type: application/json时，不会设置Content-Length，此时服务端无法判断长度，
 * 并且是通过Transfer-Encoding: chunked的方式发送给客户端，因此一定会做压缩。
 **/
@Configuration
public class GzipFilterConfig {

    @Bean
    public FilterRegistrationBean<AddContentLengthFilter> filterRegistrationBean() {
        FilterRegistrationBean<AddContentLengthFilter> filterBean = new FilterRegistrationBean<>();
        filterBean.setFilter(new AddContentLengthFilter());
        filterBean.setUrlPatterns(Collections.singletonList("*"));
        return filterBean;
    }

    static class AddContentLengthFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            ContentCachingResponseWrapper cacheResponseWrapper;
            if (!(response instanceof ContentCachingResponseWrapper)) {
                cacheResponseWrapper = new ContentCachingResponseWrapper(response);
            } else {
                cacheResponseWrapper = (ContentCachingResponseWrapper) response;
            }
            filterChain.doFilter(request, cacheResponseWrapper);
            // 写入数据长度 单位为b 例如 Content-Length: 1575045,以解决 min-response-size配置无效的问题
            cacheResponseWrapper.copyBodyToResponse();
        }
    }

}